package com.nuanshui.framework.utils.redis;

import com.alibaba.fastjson.JSON;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.framework.utils.serializer.SerializationUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import redis.clients.jedis.BuilderFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.Tuple;

import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
/**
 * redis工具类
 * @ClassName: JedisUtil 
 * @author guohao
 * @date 2015年4月14日 下午1:37:51 
 *
 */
@Service
public class JedisUtil  {
    private static final Logger logger = LoggerFactory.getLogger(JedisUtil.class);
    private static final String DEFAULT_CHARSET = "UTF-8";
    private MasterSlavePool jedisPool;
    private JedisStatistics jedisStatistics = new JedisStatistics();
    private ConcurrentHashMap<String, RedisLock> redisClocks = new ConcurrentHashMap<String, RedisLock>();
    
   
    public boolean clock(String key) {
			 RedisLock redisLock = new RedisLock(jedisPool); 
			 boolean result = redisLock.lock(key);
			 if(result) {
				 redisClocks.put(key,redisLock);
			 }	 
			 return result;
    }
    
    public void unclock(String key) {
    		RedisLock redisLock = redisClocks.get(key);
    		if(redisLock !=null) redisLock.unlock(key);
    		redisClocks.remove(key);			
    }
    
    public JedisStatistics getJedisStatistics() {
		return jedisStatistics;
	}

	/**
     * @see redis.clients.jedis.Jedis#append(String, String)
     */
    public Long append(final String key, final String value) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getMasterResource();
            return jedis.append(key, value);
        } catch (Exception ex) {
            logger.error("", ex);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#bitcount(String)
     */
    public Long bitcount(final String key) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.bitcount(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#bitcount(String, long, long)
     */
    public Long bitcount(final String key, long start, long end) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.bitcount(key, start, end);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#smembers(String)
     */
    public Set<String> smembers(String key) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.smembers(key);
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * set集合中是否存在某个值
     * @author fuxinlin
     * @date 2016年5月10日下午7:31:50
     * @param key
     * @param member
     * @return
     */
    public boolean sismember(String key,String member) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.sismember(key, member);
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
        return false;
    }
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public  LinkedHashSet smembersObj(String key) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            Set<byte[]> set =  jedis.smembers(key.getBytes());
            LinkedHashSet t = new LinkedHashSet();
            
            for(byte[] b  :set){
            	t.add(SerializationUtils.deserialize(b));
            }
            return t;
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
        return null;
    }

    public Long sadd(String key,Object obj) {
    	 Jedis jedis = null;
         try {
              jedis = jedisPool.getMasterResource();
             return jedis.sadd(key.getBytes(), SerializationUtils.serialize(obj));
         } catch (Exception e) {
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }
         return null;
    }

    public Long sadd(String key,String obj) {
   	    Jedis jedis = null;
        try {
             jedis = jedisPool.getMasterResource();
            return jedis.sadd(key,obj);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    public Long scard(String key){
    	 Jedis jedis = null;
         try {
              jedis = jedisPool.getMasterResource();
             return jedis.scard(key);
         } catch (Exception e) {
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }
         return 0L;
    }
    
    /**
     * @see redis.clients.jedis.Jedis#sinter(String...)
     */
    public Set<String> sinter(final String... keys) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.sinter(keys);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#srem(String, String...)
     */
    public Long srem(final String key, final String... members) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getMasterResource();
            return jedis.srem(key, members);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    public void srem(final String key, final Object... members) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getMasterResource();
             if(members != null) {
            	 for(Object object :members) {
            		 jedis.srem(key.getBytes(),SerializationUtils.serialize(object));
            	 }
             }        
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
    }

    public void subscribe(final JedisPubSub jedisPubSub, final String... channels) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getReadableResource();
            jedis.subscribe(jedisPubSub, channels);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
    }
    
    public void psubscribe(final JedisPubSub jedisPubSub, final String... channels) {
        Jedis jedis = null;
        try {
            jedis = jedisPool.getReadableResource();
            jedis.psubscribe(jedisPubSub, channels);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
    }

    public Long publish(final String channel, final String message) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.publish(channel, message);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

  
    
    /*************************list(列表)部分************************************/

    /**
     * @see redis.clients.jedis.Jedis#lrange(String, long, long)
     */
    public List<byte[]> lrange(final String key, final long start, final long end) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.lrange(key.getBytes(), start, end);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    public <T extends Object> List<T> lrangeObj(final String key, final long start, final long end,Class<T> clazz) {
        Jedis jedis = null;
        try {
        	 List<T> list = new ArrayList<T>();
        	
             jedis = jedisPool.getReadableResource();
             List<String> results =  jedis.lrange(key, start, end);
             for(String result  :results){   
            	 LogUtil.info(logger,result);
            	 list.add(JSON.parseObject(result,clazz));
             }
             return list;
        } catch (Exception e) {
        	e.printStackTrace();
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    public <T extends Object>  T lpop(String key,Class<T> clazz) {
    	Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             String value = jedis.lpop(key);
             return JSON.parseObject(value,clazz);          
        } catch (Exception e) {
        	e.printStackTrace();
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
	public  List lrangeObj(final String key, final long start, final long end,Type type) {
        Jedis jedis = null;
        try {
        	 List list = new ArrayList();
        	
             jedis = jedisPool.getReadableResource();
             List<String> results =  jedis.lrange(key, start, end);
             for(String result  :results){     	
            	 list.add(JSON.parseObject(result,type));
             }
             return list;
        } catch (Exception e) {
        	e.printStackTrace();
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    /**
     * 获取列表中的第一条数据
     * @param key
     * @param clazz
     * @return
     */
    public <T extends Object>  T  lfirst(final String key,Class<T>clazz) {
    	Jedis jedis = null;
        try {
        	 new ArrayList<T>();
        	
             jedis = jedisPool.getReadableResource();
             if(jedis.llen(key)<=0) return null;
             List<String> results =  jedis.lrange(key, 0, 1);
             return JSON.parseObject(results.get(0),clazz);
        } catch (Exception e) {
        	e.printStackTrace();
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    	
    }
    
    public <T extends Object> List<T> lrangeAllObj(final String key,Class<T>clazz) {
        Jedis jedis = null;
        try {
        	 List<T> list = new ArrayList<T>();
        	
             jedis = jedisPool.getReadableResource();
             List<String> results =  jedis.lrange(key, 0, -1);
             for(String result  :results){
            	 list.add(JSON.parseObject(result,clazz));
             }
             return list;
        } catch (Exception e) {
        	e.printStackTrace();
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return new ArrayList<T>();
    }

    /**
     * @see redis.clients.jedis.Jedis#lrange(String, long, long)
     */
    public List<String> lrangeString(final String key, final long start, final long end) {
        return BuilderFactory.STRING_LIST.build(lrange(key, start, end));
    }
    
    /**
     * list 尾部插入
     * @param 
     * @author guohao
     * @date 2015年6月2日 上午11:29:52
     */
    public void rpush(final String key, final byte[]... strings) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            jedis.rpush(key.getBytes(), strings);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    }
    /**
     * list 尾部插入   
     * @param 
     * @author guohao
     * @date 2015年6月2日 上午11:30:22
     */
    @SuppressWarnings("rawtypes")
	public void rpush(final String key,Collection objs) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             for(Object obj :objs) {
            	 jedis.rpush(key,JSON.toJSONString(obj));
             }      
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    }   
    
    public void lset(final String key,Integer index,Object obj) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            jedis.lset(key, index, JSON.toJSONString(obj));     
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    }   
    
    
    
    
    /**
     * list 头部插入   
     * @param 
     * @author guohao
     * @date 2015年6月2日 上午11:30:22
     */
    public void rpush(final String key,Object obj) {
    	
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             jedis.rpush(key,JSON.toJSONString(obj));      
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    } 
    /**
     * list 头部插入
     * @param 
     * @author guohao
     * @date 2015年6月2日 上午11:31:07
     */
    public void lpush(final String key,Collection<Object> objs) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             for(Object obj :objs) {
            	 jedis.lpush(key,JSON.toJSONString(obj));
             }      
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    }
    public void lpush(final String key,Object obj) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             jedis.lpush(key,JSON.toJSONString(obj));     
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

    }
    /**
     * list长度
     * @param 
     * @author guohao
     * @date 2015年6月2日 上午11:32:25
     */
    public Long llen(String key) {
    	 Jedis jedis = null;
         try {
              jedis = jedisPool.getReadableResource();
              return jedis.llen(key);
         } catch (Exception e) {
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }
         return 0L;
    }
    
    public void lrem(String key,Object obj) {
    	 Jedis jedis = null;
         try {
              jedis = jedisPool.getReadableResource();
               jedis.lrem(key, 0,JSON.toJSONString(obj) );
         } catch (Exception e) {
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }    	
    }
    
    @SuppressWarnings("rawtypes")
	public void lremObj(String key,Object obj) {
   	 Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             List list =  this.lrangeObj(key, 0, -1,Object.class);
             for(Object o :list){
            	 if(obj.equals(o)){
            		 jedis.lrem(key.getBytes(),0, SerializationUtils.serialize(o));
            		 
            	 }
             }
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }    	
   }
    
   /**********************String部分*************************************/
    
    public String set(final String key, String value) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             jedis.set(key, value);
            return jedis.set(key, value);
        } catch (Exception e) {
            logger.error("set value error", e);
            return null;
        }finally {
            returnResource(jedis);
        }
    }
    
    
    public String set(final String key, byte[] value) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.set(key.getBytes(), value);
        } catch (Exception e) {
            logger.error("set value error", e);
            return null;
        }finally {
            returnResource(jedis);
        }
    }
    
    public String setex(final String key, final int seconds, final String value) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.setex(key, seconds, value);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    public Long setnx(final String key, final String value) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.setnx(key, value);
        } catch (Exception e) {
            logger.error("");
            return null;
        }finally {
            returnResource(jedis);
        }
    }

    public Long setnx(final String key, final String value, int seconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            Long result = jedis.setnx(key, value);
            if (result == 1) {
                jedis.expire(key, seconds);
            }
            // 为了防止没有设置过期时间的key存在
            if (jedis.ttl(key) == -1) {
                jedis.expire(key, seconds);
            }
            return result;
        } catch (Exception e) {
            logger.error("set value error", e);
            return 0L;
        }finally {
            returnResource(jedis);
        }
    }
    
    /**
     * @see redis.clients.jedis.Jedis#get(String)
     */
    public String get(final String key) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.get(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    public byte[] get(final byte[] key) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.get(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    

    /**
     * 获取key对应的 value 值，如果没有，则执行 ifAbsent 然后缓存并返回结果
     *
     * @param key           redis key
     * @param ifAbsent      如果缓存中不存在，则根据这个获取值并缓存
     * @param expireSeconds 过期时间
     * @return value
     */
    public String get(final String key, final Callable<String> ifAbsent, final int expireSeconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            String value = jedis.get(key);
            if (value == null) {
                jedisStatistics.commandGetExecuted(false);
                try {
                    value = ifAbsent.call();
                    if (value != null) {
                        setex(key, expireSeconds, value);
                    }
                } catch (Exception e) {
                    logger.error("", e);
                }
            } else {
                jedisStatistics.commandGetExecuted(true);
            }
            return value;
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#getSet(String, String)
     */
    public String getSet(final String key, final String value) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.getSet(key, value);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    /**
     * @see redis.clients.jedis.Jedis#incr(String)
     */
    public Long incr(final String key) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.incr(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    public Long decr(final String key) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.decr(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#incrBy(String, long)
     */
    public Long incrBy(final String key, long integer) {
    	Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.incrBy(key, integer);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    /**
     * @see redis.clients.jedis.Jedis#mget(String...)
     */
    public List<String> mget(final String... keys) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.mget(keys);
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);

        }
        return null;
    }
    
    /**
     * set Object to redis
     *
     * @param key
     * @param value
     * @return Status code reply
     * @throws java.io.IOException
     */
    public void setObject(final String key, Object value) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
             jedis.set(key,JSON.toJSONString(value));
        } catch (Exception e) {
        	e.printStackTrace();
        	LogUtil.error(logger, "setObject ",e);
        }finally {
            returnResource(jedis);
        }
    }

    public void setObjectExpire(final String key ,Object value,int time){
        Jedis jedis =null;
        try {
            jedis = jedisPool.getReadableResource();
            jedis.set(key,JSON.toJSONString(value));
            jedis.expire(key,time);
        } catch (Exception e) {
            e.printStackTrace();
            LogUtil.error(logger, "setObject ",e);
        }finally {
            returnResource(jedis);
        }
    }

    public String setJson(final String key, Object value, final int seconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.setex(key.getBytes(DEFAULT_CHARSET), seconds, JSON.toJSONBytes(value));
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    public long setList(final String key, final int seconds, List<String> values) {
        Jedis jedis = null;
        long len = 0;
        try {
             jedis = jedisPool.getReadableResource();
            for (String str : values) {
                len = jedis.lpush(key, str);
            }
            jedis.expire(key, seconds);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return len;
    }

    /**
     * get Object from redis
     *
     * @param key
     * @return Object
     */
    public <T> T getObject(final String key,Class<T> clazz) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             return JSON.parseObject(jedis.get(key),clazz);
        } catch (Exception e) {
        	
        	e.printStackTrace();
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    public <T> T getObjectFromJson(final String key, Class<? extends T> clz) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            byte[] bytes = jedis.get(key.getBytes(DEFAULT_CHARSET));
            if (bytes != null && bytes.length > 1) {
                return JSON.parseObject(bytes, clz);
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    public <T> T getObjectFromJson(final String key, Class<? extends T> clz, final Callable<T> ifAbsent, final int expireSeconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            byte[] bytes = jedis.get(key.getBytes(DEFAULT_CHARSET));
            if (bytes != null && bytes.length > 1) {
                jedisStatistics.commandGetExecuted(true);
                return JSON.parseObject(bytes, clz);
            } else {
                jedisStatistics.commandGetExecuted(false);
                T value = ifAbsent.call();
                if (value != null) {
                    setJson(key, value, expireSeconds);
                    return value;
                }
            }
        } catch (Exception e) {
            logger.error("", e);
        }finally {
             returnResource(jedis);
        }
        return null;
    }

    public <T> List<T> getListFromJson(final String key, Class<T> clz, final Callable<List<T>> ifAbsent, final int expireSeconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            byte[] bytes = jedis.get(key.getBytes(DEFAULT_CHARSET));
            if (bytes != null && bytes.length > 1) {
                jedisStatistics.commandGetExecuted(true);
                return JSON.parseArray(new String(bytes, DEFAULT_CHARSET), clz);
            } else {
                jedisStatistics.commandGetExecuted(false);
                List<T> value = ifAbsent.call();
                if (value != null) {
                    setJson(key, value, expireSeconds);
                    return value;
                }
            }
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
        return null;
    }

    /**********************key(键值部分)***********************************/
    /**
     * @see redis.clients.jedis.Jedis#del(String...)
     */
    public Long del(final String... keys) {
        Jedis jedis =null;
        try {
            jedis = jedisPool.getReadableResource();
            return jedis.del(keys);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
         returnResource(jedis);
        }
        return null;
    }
    
    public Long delAll(final String  key) {
        Jedis jedis =null;
        Long count = 0L;
        try {
            jedis = jedisPool.getReadableResource();
            Set<String> keys   = jedis.keys(key+"*");
            for(String k :keys){
            	count+=jedis.del(k);
            }
            return count;
        } catch (Exception e) {
            logger.error("", e);
        }finally {
         returnResource(jedis);
        }
        return null;
    }
    
    
    public Long del(final byte[]... keys) {
        Jedis jedis =null;
        try {
            jedis = jedisPool.getReadableResource();
            return jedis.del(keys);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
         returnResource(jedis);
        }
        return null;
    }
    
    
    public void clear() {
    	 Jedis jedis =null;
         try {
              jedis = jedisPool.getReadableResource();
             
              jedis.flushAll();
         } catch (Exception e) {
             logger.error("", e);
         }finally {
          returnResource(jedis);
         }
    	
    }

    

    /**
     * @see redis.clients.jedis.Jedis#keys(String)
     */
    public Set<String> keys(final String pattern) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.keys(pattern);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
         returnResource(jedis);
        }
        return null;
    }
    
    
    public Set<byte[]> keys(final byte[] pattern) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.keys(pattern);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
         returnResource(jedis);
        }
        return null;
    }

   

    /**
     * @see redis.clients.jedis.Jedis#expire(String, int)
     */
    public Long expire(final String key, final int seconds) {
    	 Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.expire(key, seconds);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
           }
        return null;
    }
    
    public Long pexpire(final String key, final long milliseconds) {
    	 Jedis jedis = null;
    	try {
             jedis = jedisPool.getReadableResource();
            return jedis.pexpire(key, milliseconds);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#expire(byte[], int)
     */
    public Long expire(final byte[] key, final int seconds) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.expire(key, seconds);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

   

    /**
     * @see redis.clients.jedis.Jedis#exists(String)
     */
    public Boolean exists(final String key) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.exists(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#ttl(String)
     */
    public Long ttl(final String key) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.ttl(key);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }
    
    
    
    /*************************SortedSet（有序集合）****************************************/

    /**
     * @see redis.clients.jedis.Jedis#zincrby(String, double, String)
     */
    public Double zincrby(final String key, final double score, final String member) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.zincrby(key, score, member);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }

        return null;

    }

    /**
     * @see redis.clients.jedis.Jedis#zrangeWithScores(String, long, long)
     */
    public Set<Tuple> zrangeWithScores(final String key, final long start, final long end) {
        Jedis jedis =null;
        try {
             jedis = jedisPool.getReadableResource();
            return jedis.zrangeWithScores(key, start, end);
        } catch (Exception e) {
            logger.error("", e);
        }finally {
            returnResource(jedis);
        }
        return null;
    }

    /**
     * @see redis.clients.jedis.Jedis#zinterstore(String, String...)
     */
    public void zUnionStore(final String destinationKey, final String... sets) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
            jedis.zunionstore(destinationKey, sets);
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
    }
    
    public void zaddObj(String key,long score,Object obj) {
    	 Jedis jedis = null;
         try {
              jedis = jedisPool.getReadableResource();
              jedis.zadd(key,score,JSON.toJSONString(obj));     
         } catch (Exception e) {
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }
    }
    
    /**
     * 获取大于score的所有数据
     * @param @param key
     * @param @param score
     * @param @param clazz
     * @param @return
     * @author guohao
     * @date 2016年5月12日 上午9:55:19
     * @since $
     */
    public <T extends Object> List<T> zrangByMinScore(String key,long score,Class<T> clazz) {
    	 Jedis jedis = null;
         try {
         	 List<T> list = new ArrayList<T>();
         	
              jedis = jedisPool.getReadableResource();
              Set<String> results =  jedis.zrangeByScore(key, "("+score, "+inf");
              for(String result  :results){     	
             	 list.add(JSON.parseObject(result,clazz));
              }
              return list;
         } catch (Exception e) {
         	e.printStackTrace();
             logger.error("", e);
         }finally {
             returnResource(jedis);
         }
         return new ArrayList<T>();
    }
    
    
    
    public void hset(final String key,String filed,Object value) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             jedis.hset(key,filed,JSON.toJSONString(value));
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
    }
    
    public <T extends Object> T hget(final String key,String filed,Class<T> clazz) {
        Jedis jedis = null;
        try {
             jedis = jedisPool.getReadableResource();
             return JSON.parseObject(jedis.hget(key,filed),clazz);
        } catch (Exception e) {
            logger.error("", e);
        }
        finally {
            returnResource(jedis);
        }
        return null;
    }
    
 


    

 

//    @PostConstruct
//    private void jmxRegister() {
//        String jmxNameBase = "redis.pool:redis=" + this.jedisPool.getRedisName() + ",name=";
//        String jmxNamePrefix = "statistics";
//        ObjectName objectName = null;
//        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
//        int i = 1;
//        boolean registered = false;
//        while (!registered) {
//            try {
//                ObjectName objName;
//                // Skip the numeric suffix for the first pool in case there is
//                // only one so the names are cleaner.
//                if (i == 1) {
//                    objName = new ObjectName(jmxNameBase + jmxNamePrefix);
//                } else {
//                    objName = new ObjectName(jmxNameBase + jmxNamePrefix + i);
//                }
//                mbs.registerMBean(this.jedisStatistics, objName);
//                objectName = objName;
//                registered = true;
//            } catch (InstanceAlreadyExistsException e) {
//                // Increment the index and try again
//                i++;
//            } catch (MalformedObjectNameException | MBeanRegistrationException | NotCompliantMBeanException e) {
//                // Shouldn't happen. Skip registration if it does.
//                registered = true;
//            }
//        }
//        oname = objectName;
//    }

//    @PreDestroy
//    private void jmxUnregister() {
//        if (oname != null) {
//            try {
//                ManagementFactory.getPlatformMBeanServer().unregisterMBean(
//                        oname);
//            } catch (MBeanRegistrationException | InstanceNotFoundException e) {
//                logger.error("jmxUnregister error", e);
//            }
//        }
//    }

    public void setJedisPool(MasterSlavePool jedisPool) {
        this.jedisPool = jedisPool;
    }

    /**
     * 暂时只支持master
     * @param jedis
     */
    public void returnResource(Jedis jedis) {
        //   String key = jedis.getClient().getHost() + ":" + jedis.getClient().getPort();
//        if (slavePool != null && slavePool.getHostString().equalsIgnoreCase(key)) {
//            slavePool.returnResource(jedis);
//        } else if (masterPool.getHostString().equalsIgnoreCase(key)) {
        if(jedis!=null) {
            jedisPool.returnResource(jedis);
        }
//        } else {
//            logger.error("can't return jedis {} to pool!", key);
//        }
    }
}
